package com.cssw.fyzb.event.service.live;

import com.cssw.fyzb.core.mao.live.LivePkMao;
import com.cssw.fyzb.core.mao.live.LiveStatMao;
import com.cssw.fyzb.core.mao.live.UserLiveMao;
import com.cssw.fyzb.core.model.mos.AudienceMo;
import com.cssw.fyzb.core.model.mos.LivePkMo;
import com.cssw.fyzb.core.model.mos.LiveStatMo;
import com.cssw.fyzb.core.model.mos.UserLiveMo;
import com.cssw.fyzb.event.cache.Cache;
import com.cssw.fyzb.event.cache.CacheKeys;
import com.cssw.fyzb.event.config.TpsClient;
import com.cssw.fyzb.core.model.vo.live.RankItemVo;
import com.cssw.fyzb.core.model.vo.live.RankVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: YangYiQun
 * @Date: 2020/12/22 22:11
 */
@Service
public class LiveServiceImpl implements LiveService {

    private static final Logger logger = LoggerFactory.getLogger(LiveServiceImpl.class);

    private static final Integer RANK_SIZE = 3;

    @Autowired
    private UserLiveMao userLiveMao;

    @Autowired
    private TpsClient tpsClient;

    @Autowired
    private LivePkMao livePkMao;

    @Autowired
    private LiveStatMao liveStatMao;

    @Override
    public void reRank(Long liveId) {
        // 打赏排序改变
        RankVo rank = getCurrentRank(liveId);
        RankVo cache = Cache.get(CacheKeys.rewardRankKey(liveId));

        if (rank == null && cache == null) {
            return;
        }

        if (cache == null) {
            // 排行改变了
            Cache.put(CacheKeys.rewardRankKey(liveId), rank);

            sendGroupCustomMsg(liveId, "rankChange", rank);
        } else if (rank != null) {

            // 排序变了
            if (isChange(rank.getList(), cache.getList()) || rank.getTotal() != cache.getTotal()) {

                // 排行改变了
                Cache.put(CacheKeys.rewardRankKey(liveId), rank);

                sendGroupCustomMsg(liveId, "rankChange", rank);
            }
        }
    }

    // 打赏排序改变
    public void rePkRank(Long liveId, Long pkId) {
        RankVo rank = getCurrentPkRank(liveId, pkId);
        RankVo cache = Cache.get(CacheKeys.pkRankKey(liveId));


        if (rank == null && cache == null) {
            return;
        }

        if (cache == null) {
            // 排行改变了
            Cache.put(CacheKeys.pkRankKey(liveId), rank);
            //通知PK排行变化
            notifyPkRankChange(pkId, liveId, rank);
        }
        else if (rank != null) {

            // 排序变了
            if (isChange(rank.getList(), cache.getList()) || rank.getTotal() != cache.getTotal()) {

                // 排行改变了
                Cache.put(CacheKeys.pkRankKey(liveId), rank);

                //通知PK排行变化
                notifyPkRankChange(pkId, liveId, rank);
            }
        }
    }

    private void notifyPkRankChange(Long pkId, Long liveId, RankVo rank){
        List<LivePkMo> livePkMos = livePkMao.findByPk(pkId);

        //通知两个主播间
        if (null != livePkMos) {
            String cmd = null;
            for (LivePkMo livePkMo : livePkMos) {
                if (livePkMo.getLiveId().toString().equals(liveId)) {
                    cmd = "pkRankChange";
                } else {
                    cmd = "pkRankChangeTo";
                }
                sendGroupCustomMsg(livePkMo.getLiveId(), cmd, rank);
            }
        }
    }

    @Override
    public void like(Long liveId, Long userId) {
        liveStatMao.incLikes(liveId);

        LiveStatMo liveStatMo = liveStatMao.findByLiveId(liveId);
        if (null == liveStatMo){
            return;
        }

        Map<String, Object> data = new HashMap<>();
        data.put("cmd", "liveLike");
        data.put("likes", liveStatMo.getLikes());

        tpsClient.sendGroupCustomMsg(liveId, data);
    }

    private RankVo getCurrentPkRank(Long liveId, Long pkId) {
        LivePkMo pk = livePkMao.findByLiveAndPk(liveId, pkId);
        if (pk == null || pk.getAudiences() == null || pk.getAudiences().isEmpty()) {
            return null;
        }

        RankVo rankVo = new RankVo();
        // 总礼物数
        rankVo.setTotal(pk.getTotal());

        List<AudienceMo> audiences = new ArrayList<>(
                pk.getAudiences()
                        .stream()
                        .sorted((o1, o2) -> o2.getReward() - o1.getReward())
                        .collect(Collectors.toList())
        );

        ArrayList<RankItemVo> items = new ArrayList<>();
        int size = audiences.size() > RANK_SIZE ? RANK_SIZE : audiences.size();
        AudienceMo audienceMo = null;
        for (int i = 0; i < size; i++) {
            audienceMo = audiences.get(i);
            RankItemVo item = new RankItemVo();
            item.setNo(i + 1);
            item.setUserId(audienceMo.getUserId());
            items.add(item);
        }

        rankVo.setList(items);

        return rankVo;
    }


    private void sendGroupCustomMsg(Long liveId, String cmd, RankVo rank) {
        Map<String, Object> data = new HashMap<>();
        data.put("cmd", cmd);
        data.put("rank", rank);

        tpsClient.sendGroupCustomMsg(liveId, data);
    }

    private RankVo getCurrentRank(Long liveId) {
        UserLiveMo list = userLiveMao.findByLiveId(liveId);
        if (list == null || null == list.getAudiences() || list.getAudiences().isEmpty()) {
            return null;
        }

        RankVo rankVo = new RankVo();
        rankVo.setTotal(list.getAudiences().size());


        List<AudienceMo> audiences = new ArrayList<>(
                list.getAudiences()
                        .stream()
                        .sorted((o1, o2) -> o2.getReward() - o1.getReward())
                        .collect(Collectors.toList())
        );

        ArrayList<RankItemVo> items = new ArrayList<>();
        int size = audiences.size() > RANK_SIZE ? RANK_SIZE : audiences.size();
        AudienceMo audienceMo = null;
        for (int i = 0; i < size; i++) {
            audienceMo = audiences.get(i);
            RankItemVo item = new RankItemVo();
            item.setNo(i + 1);
            item.setUserId(audienceMo.getUserId());
            items.add(item);
        }

        rankVo.setList(items);

        return rankVo;
    }


    public boolean isChange(List<RankItemVo> ranks, List<RankItemVo> others) {

        // 有一个为空 或者 长度不等
        if (ranks == null || others == null || ranks.size() != others.size()) {
            return true;
        }

        int size = ranks.size();
        for (int i = 0; i < size; i++) {
            RankItemVo rank = ranks.get(i);
            RankItemVo other = others.get(i);
            if (rank.getUserId() != other.getUserId()) {
                return true;
            }
        }

        return false;
    }

}
